Applied exercises
This exercise relates to the College data set, which can be found in the file College.csv. It contains a number of variables for 777 different universities and colleges in the US. The variables are:
• Private : Public/private indicator • Apps : Number of applications received • Accept : Number of applicants accepted • Enroll : Number of new students enrolled • Top10perc : New students from top 10 % of high school class • Top25perc : New students from top 25 % of high school class • F.Undergrad : Number of full-time undergraduates • P.Undergrad : Number of part-time undergraduates • Outstate : Out-of-state tuition • Room.Board : Room and board costs • Books : Estimated book costs • Personal : Estimated personal spending • PhD : Percent of faculty with Ph.D.’s • Terminal : Percent of faculty with terminal degree • S.F.Ratio : Student/faculty ratio • perc.alumni : Percent of alumni who donate • Expend : Instructional expenditure per student • Grad.Rate : Graduation rate Before reading the data into R, it can be viewed in Excel or a text editor.
- Use the read.csv() function to read the data into R. Call the loaded data college. Make sure that you have the directory set to the correct location for the data.
- Look at the data using the fix() function. You should notice that the first column is just the name of each university. We don’t really want R to treat this as data. However, it may be handy to have these names for later. Try the following commands:
In the package version of College the row names are already assigned as the unviersity names.
- Use the summary() function to produce a numerical summary of the variables in the data set.
- Use the pairs() function to produce a scatterplot matrix of the first ten columns or variables of the data. Recall that you can reference the first ten columns of a matrix A using A[,1:10].
- Use the plot() function to produce side-by-side boxplots of Outstate versus Private.
- Create a new qualitative variable, called Elite, by binning the Top10perc variable. We are going to divide universities into two groups based on whether or not the proportion of students coming from the top 10% of their high school classes exceeds 50 %.
library(ggplot2)
lapply(College, summary)
pairs(College[1:10])
boxplot(College$Outstate ~ College$Private)
College$Elite <- ifelse(College$Top10perc > 50, "Yes", "No")
Use the summary() function to see how many elite univer- sities there are. Now use the plot() function to produce side-by-side boxplots of Outstate versus Elite.

- Use the hist() function to produce some histograms with differing numbers of bins for a few of the quantitative vari- ables. You may find the command par(mfrow=c(2,2)) useful: it will divide the print window into four regions so that four plots can be made simultaneously. Modifying the arguments to this function will divide the screen in other ways.
hist(College$Enroll)

hist(College$F.Undergrad)

hist(College$PhD)

hist(College$Accept/College$Apps) # Per every application, barely anyone accepts a student.

hist(College$Grad.Rate[College$Private == "Yes"])

hist(College$Grad.Rate[College$Private == "No"])

- Continue exploring the data, and provide a brief summary of what you discover. To do
- This exercise involves the Auto data set studied in the lab. Make sure that the missing values have been removed from the data.
- Which of the predictors are quantitative, and which are quali- tative?
lapply(Auto[-ncol(Auto)], summary)
$mpg
Min. 1st Qu. Median Mean 3rd Qu. Max.
9.00 17.00 22.75 23.45 29.00 46.60
$cylinders
Min. 1st Qu. Median Mean 3rd Qu. Max.
3.000 4.000 4.000 5.472 8.000 8.000
$displacement
Min. 1st Qu. Median Mean 3rd Qu. Max.
68.0 105.0 151.0 194.4 275.8 455.0
$horsepower
Min. 1st Qu. Median Mean 3rd Qu. Max.
46.0 75.0 93.5 104.5 126.0 230.0
$weight
Min. 1st Qu. Median Mean 3rd Qu. Max.
1613 2225 2804 2978 3615 5140
$acceleration
Min. 1st Qu. Median Mean 3rd Qu. Max.
8.00 13.78 15.50 15.54 17.02 24.80
$year
Min. 1st Qu. Median Mean 3rd Qu. Max.
70.00 73.00 76.00 75.98 79.00 82.00
$origin
Min. 1st Qu. Median Mean 3rd Qu. Max.
1.000 1.000 1.000 1.577 2.000 3.000
- What is the range of each quantitative predictor? You can answer this using the range() function.
lapply(Auto[c("mpg", "displacement", "horsepower", "weight", "acceleration", "year")], range)
$mpg
[1] 9.0 46.6
$displacement
[1] 68 455
$horsepower
[1] 46 230
$weight
[1] 1613 5140
$acceleration
[1] 8.0 24.8
$year
[1] 70 82
- What is the mean and standard deviation of each quantitative predictor?
lapply(Auto[c("mpg", "displacement", "horsepower", "weight", "acceleration", "year")], mean)
$mpg
[1] 23.44592
$displacement
[1] 194.412
$horsepower
[1] 104.4694
$weight
[1] 2977.584
$acceleration
[1] 15.54133
$year
[1] 75.97959
- Now remove the 10th through 85th observations. What is the range, mean, and standard deviation of each predictor in the subset of the data that remains?
basic <- function(x) {
summary <- c(mean = mean(x, na.rm = T), range = range(x, na.rm = T), sd = sd(x, na.rm = T))
summary
}
lapply(Auto[-(10:85), -ncol(Auto)], basic)
- Using the full data set, investigate the predictors graphically, using scatterplots or other tools of your choice. Create some plots highlighting the relationships among the predictors. Comment on your findings.

It’s interesting to look the mpg is negatively related to displacement, horsepower and weight in a similar fashion. In fact, the correlation are:
correlations <- c(first = cor(Auto$mpg, Auto$displacement), second = cor(Auto$mpg, Auto$horsepower), third = cor(Auto$mpg, Auto$weight))
correlations
first second third
-0.8051269 -0.7784268 -0.8322442
All within a 5 figure difference. and above -0.70. In contrast, the correlations between displacement, horsepower and weight are strong and positive.
correlations2 <- c(displa_horse = cor(Auto$displacement, Auto$horsepower), displace_weight = cor(Auto$displacement, Auto$weight), horsep_weight = cor(Auto$horsepower, Auto$weight))
correlations2
displa_horse displace_weight horsep_weight
0.8972570 0.9329944 0.8645377
plot(Auto$displacement, Auto$horsepower)

plot(Auto$displacement, Auto$weight)

plot(Auto$horsepower, Auto$weight)

- Suppose that we wish to predict gas mileage (mpg) on the basis of the other variables. Do your plots suggest that any of the other variables might be useful in predicting mpg? Justify your answer.
Yeah, just as we saw in the matrix scatterplot, mpg is highly correlated with several variables. Not only visually, but the correlation coefficients are substantial.
- To begin, load in the Boston data set.
How many rows are in this data set? How many columns? What do the rows and columns represent?
dim(Boston)
[1] 506 14
The data has 506 rows and 14 columns. Each row represents housing values in suburbs from Boston. See help(Boston).
- Make some pairwise scatterplots of the predictors (columns) in this data set. Describe your findings.
plot(Boston)

Well, besides the array of correlations that you can find in the scatterplot, I find interesting that there’s some clear non-linear patterns such as in nox ~ dis as well as Istat ~ medv and rm ~ Istat.
- Are any of the predictors associated with per capita crime rate? If so, explain the relationship.
crim is correlated with age, div, lstat and medv. The relationships are not straightforward though.




As the proportion of owner-occupied units buitl prior to 1940 increases, crime rates increase. But note that there’s threshold effects. At around 40% crime rates start to increase and only around 80% it becomes substantial. This relationship might not be that strong linearly, but more non-linear.
With dis (distance to five Boston employment centres), crime rates are higher only when employment centers are close, but as it passes increases over 4, crime rates set at 0.
With lstat it’s similar as with age, crime rates increases only after some value, more or less around 15. It seems that crime rates are not linearly related to almost any variable; it’s mostly non-linearly related. Same pattern with medv
- Do any of the suburbs of Boston appear to have particularly high crime rates? Tax rates? Pupil-teacher ratios? Comment on the range of each predictor.
Boxplot(Boston$crim)
[1] 381 419 406 411 415 405 399 428 414 418

Above the graph we can see the outliers which have significantly higher crime rates than the overall distribution. 10 suburbs, so not specifically a small bunch.
Boxplot(Boston$ptratio)
[1] 197 198 199 258 259 260 261 262 263 264

Boxplot(Boston$tax)

ptratio does have some outliers, but they’re not the same ones as with crime rates. Surprisingly, tax doesn`t have any outliers, and the distribution is pretty smooth.
for (i in c("crim", "ptratio", "tax")) {
print(range(Boston[, i]))
}
[1] 0.00632 88.97620
[1] 12.6 22.0
[1] 187 711
The range of crime rates can be as high as 88% and as low as 0%, quite some diversity between suburbs. Student-teacher ratio is much smaller, with a maximum of 22 students and a minimum of 13. Tax ranges from 187 to 711.
- How many of the suburbs in this data set bound the Charles river?
table(Boston$chas)
0 1
471 35
35 suburs.
- What is the median pupil-teacher ratio among the towns in this data set?
median(Boston$ptratio)
[1] 19.05
19 pupils per teacher.
- Which suburb of Boston has lowest median value of owner- occupied homes? What are the values of the other predictors for that suburb, and how do those values compare to the overall ranges for those predictors? Comment on your findings.
Boston[Boston$medv == min(Boston$medv), ]
Actually, both suburb 399 and 406 have the same lowest media value, which is 5.
First, both suburs have virtually the same values for all predictors except for the crim, lstat and black.
- In this data set, how many of the suburbs average more than seven rooms per dwelling? More than eight rooms per dwelling? Comment on the suburbs that average more than eight rooms per dwelling.
LS0tCnRpdGxlOiAiUiBOb3RlYm9vayIKb3V0cHV0OiBodG1sX25vdGVib29rCi0tLQoKIyBBcHBsaWVkIGV4ZXJjaXNlcwoKVGhpcyBleGVyY2lzZSByZWxhdGVzIHRvIHRoZSBDb2xsZWdlIGRhdGEgc2V0LCB3aGljaCBjYW4gYmUgZm91bmQgaW4gdGhlIGZpbGUgQ29sbGVnZS5jc3YuIEl0IGNvbnRhaW5zIGEgbnVtYmVyIG9mIHZhcmlhYmxlcyBmb3IgNzc3IGRpZmZlcmVudCB1bml2ZXJzaXRpZXMgYW5kIGNvbGxlZ2VzIGluIHRoZSBVUy4gVGhlIHZhcmlhYmxlcyBhcmU6CgrigKIgUHJpdmF0ZSA6IFB1YmxpYy9wcml2YXRlIGluZGljYXRvcgrigKIgQXBwcyA6IE51bWJlciBvZiBhcHBsaWNhdGlvbnMgcmVjZWl2ZWQK4oCiIEFjY2VwdCA6IE51bWJlciBvZiBhcHBsaWNhbnRzIGFjY2VwdGVkCuKAoiBFbnJvbGwgOiBOdW1iZXIgb2YgbmV3IHN0dWRlbnRzIGVucm9sbGVkCuKAoiBUb3AxMHBlcmMgOiBOZXcgc3R1ZGVudHMgZnJvbSB0b3AgMTAgJSBvZiBoaWdoIHNjaG9vbCBjbGFzcyDigKIgVG9wMjVwZXJjIDogTmV3IHN0dWRlbnRzIGZyb20gdG9wIDI1ICUgb2YgaGlnaCBzY2hvb2wgY2xhc3Mg4oCiIEYuVW5kZXJncmFkIDogTnVtYmVyIG9mIGZ1bGwtdGltZSB1bmRlcmdyYWR1YXRlcwrigKIgUC5VbmRlcmdyYWQgOiBOdW1iZXIgb2YgcGFydC10aW1lIHVuZGVyZ3JhZHVhdGVzCuKAoiBPdXRzdGF0ZSA6IE91dC1vZi1zdGF0ZSB0dWl0aW9uCuKAoiBSb29tLkJvYXJkIDogUm9vbSBhbmQgYm9hcmQgY29zdHMK4oCiIEJvb2tzIDogRXN0aW1hdGVkIGJvb2sgY29zdHMK4oCiIFBlcnNvbmFsIDogRXN0aW1hdGVkIHBlcnNvbmFsIHNwZW5kaW5nCuKAoiBQaEQgOiBQZXJjZW50IG9mIGZhY3VsdHkgd2l0aCBQaC5ELuKAmXMK4oCiIFRlcm1pbmFsIDogUGVyY2VudCBvZiBmYWN1bHR5IHdpdGggdGVybWluYWwgZGVncmVlCuKAoiBTLkYuUmF0aW8gOiBTdHVkZW50L2ZhY3VsdHkgcmF0aW8K4oCiIHBlcmMuYWx1bW5pIDogUGVyY2VudCBvZiBhbHVtbmkgd2hvIGRvbmF0ZQrigKIgRXhwZW5kIDogSW5zdHJ1Y3Rpb25hbCBleHBlbmRpdHVyZSBwZXIgc3R1ZGVudArigKIgR3JhZC5SYXRlIDogR3JhZHVhdGlvbiByYXRlCkJlZm9yZSByZWFkaW5nIHRoZSBkYXRhIGludG8gUiwgaXQgY2FuIGJlIHZpZXdlZCBpbiBFeGNlbCBvciBhIHRleHQgZWRpdG9yLgoKKGEpIFVzZSB0aGUgcmVhZC5jc3YoKSBmdW5jdGlvbiB0byByZWFkIHRoZSBkYXRhIGludG8gUi4gQ2FsbCB0aGUgbG9hZGVkIGRhdGEgY29sbGVnZS4gTWFrZSBzdXJlIHRoYXQgeW91IGhhdmUgdGhlIGRpcmVjdG9yeSBzZXQgdG8gdGhlIGNvcnJlY3QgbG9jYXRpb24gZm9yIHRoZSBkYXRhLgpgYGB7cn0KbGlicmFyeShJU0xSKQpoZWFkKENvbGxlZ2UpCmBgYAoKKGIpIExvb2sgYXQgdGhlIGRhdGEgdXNpbmcgdGhlIGZpeCgpIGZ1bmN0aW9uLiBZb3Ugc2hvdWxkIG5vdGljZSB0aGF0IHRoZSBmaXJzdCBjb2x1bW4gaXMganVzdCB0aGUgbmFtZSBvZiBlYWNoIHVuaXZlcnNpdHkuIFdlIGRvbuKAmXQgcmVhbGx5IHdhbnQgUiB0byB0cmVhdCB0aGlzIGFzIGRhdGEuIEhvd2V2ZXIsIGl0IG1heSBiZSBoYW5keSB0byBoYXZlIHRoZXNlIG5hbWVzIGZvciBsYXRlci4gVHJ5IHRoZSBmb2xsb3dpbmcgY29tbWFuZHM6CgpJbiB0aGUgcGFja2FnZSB2ZXJzaW9uIG9mIGBDb2xsZWdlYCB0aGUgcm93IG5hbWVzIGFyZSBhbHJlYWR5IGFzc2lnbmVkIGFzIHRoZSB1bnZpZXJzaXR5IG5hbWVzLgoKKGMpCmkuIFVzZSB0aGUgc3VtbWFyeSgpIGZ1bmN0aW9uIHRvIHByb2R1Y2UgYSBudW1lcmljYWwgc3VtbWFyeSBvZiB0aGUgdmFyaWFibGVzIGluIHRoZSBkYXRhIHNldC4KaWkuIFVzZSB0aGUgcGFpcnMoKSBmdW5jdGlvbiB0byBwcm9kdWNlIGEgc2NhdHRlcnBsb3QgbWF0cml4IG9mIHRoZSBmaXJzdCB0ZW4gY29sdW1ucyBvciB2YXJpYWJsZXMgb2YgdGhlIGRhdGEuIFJlY2FsbCB0aGF0IHlvdSBjYW4gcmVmZXJlbmNlIHRoZSBmaXJzdCB0ZW4gY29sdW1ucyBvZiBhIG1hdHJpeCBBIHVzaW5nIEFbLDE6MTBdLgppaWkuIFVzZSB0aGUgcGxvdCgpIGZ1bmN0aW9uIHRvIHByb2R1Y2Ugc2lkZS1ieS1zaWRlIGJveHBsb3RzIG9mIE91dHN0YXRlIHZlcnN1cyBQcml2YXRlLgppdi4gQ3JlYXRlIGEgbmV3IHF1YWxpdGF0aXZlIHZhcmlhYmxlLCBjYWxsZWQgRWxpdGUsIGJ5IGJpbm5pbmcgdGhlIFRvcDEwcGVyYyB2YXJpYWJsZS4gV2UgYXJlIGdvaW5nIHRvIGRpdmlkZSB1bml2ZXJzaXRpZXMgaW50byB0d28gZ3JvdXBzIGJhc2VkIG9uIHdoZXRoZXIgb3Igbm90IHRoZSBwcm9wb3J0aW9uIG9mIHN0dWRlbnRzIGNvbWluZyBmcm9tIHRoZSB0b3AgMTAlIG9mIHRoZWlyIGhpZ2ggc2Nob29sIGNsYXNzZXMgZXhjZWVkcyA1MCAlLgoKYGBge3J9CmxpYnJhcnkoZ2dwbG90MikKbGFwcGx5KENvbGxlZ2UsIHN1bW1hcnkpCgpwYWlycyhDb2xsZWdlWzE6MTBdKQoKYm94cGxvdChDb2xsZWdlJE91dHN0YXRlIH4gQ29sbGVnZSRQcml2YXRlKQoKQ29sbGVnZSRFbGl0ZSA8LSBpZmVsc2UoQ29sbGVnZSRUb3AxMHBlcmMgPiA1MCwgIlllcyIsICJObyIpCmBgYAoKVXNlIHRoZSBzdW1tYXJ5KCkgZnVuY3Rpb24gdG8gc2VlIGhvdyBtYW55IGVsaXRlIHVuaXZlci0gc2l0aWVzIHRoZXJlIGFyZS4gTm93IHVzZSB0aGUgcGxvdCgpIGZ1bmN0aW9uIHRvIHByb2R1Y2Ugc2lkZS1ieS1zaWRlIGJveHBsb3RzIG9mIE91dHN0YXRlIHZlcnN1cyBFbGl0ZS4KCmBgYHtyfQpzdW1tYXJ5KENvbGxlZ2UkRWxpdGUpCgpib3hwbG90KENvbGxlZ2UkT3V0c3RhdGUgfiBDb2xsZWdlJEVsaXRlKQpgYGAKCgp2LiBVc2UgdGhlIGhpc3QoKSBmdW5jdGlvbiB0byBwcm9kdWNlIHNvbWUgaGlzdG9ncmFtcyB3aXRoIGRpZmZlcmluZyBudW1iZXJzIG9mIGJpbnMgZm9yIGEgZmV3IG9mIHRoZSBxdWFudGl0YXRpdmUgdmFyaS0gYWJsZXMuIFlvdSBtYXkgZmluZCB0aGUgY29tbWFuZCBwYXIobWZyb3c9YygyLDIpKSB1c2VmdWw6IGl0IHdpbGwgZGl2aWRlIHRoZSBwcmludCB3aW5kb3cgaW50byBmb3VyIHJlZ2lvbnMgc28gdGhhdCBmb3VyIHBsb3RzIGNhbiBiZSBtYWRlIHNpbXVsdGFuZW91c2x5LiBNb2RpZnlpbmcgdGhlIGFyZ3VtZW50cyB0byB0aGlzIGZ1bmN0aW9uIHdpbGwgZGl2aWRlIHRoZSBzY3JlZW4gaW4gb3RoZXIgd2F5cy4KCmBgYHtyfQpoaXN0KENvbGxlZ2UkRW5yb2xsKQpoaXN0KENvbGxlZ2UkRi5VbmRlcmdyYWQpCmhpc3QoQ29sbGVnZSRQaEQpCgpoaXN0KENvbGxlZ2UkQWNjZXB0L0NvbGxlZ2UkQXBwcykgIyBQZXIgZXZlcnkgYXBwbGljYXRpb24sIGJhcmVseSBhbnlvbmUgYWNjZXB0cyBhIHN0dWRlbnQuCgpoaXN0KENvbGxlZ2UkR3JhZC5SYXRlW0NvbGxlZ2UkUHJpdmF0ZSA9PSAiWWVzIl0pCmhpc3QoQ29sbGVnZSRHcmFkLlJhdGVbQ29sbGVnZSRQcml2YXRlID09ICJObyJdKQpgYGAKdmkuIENvbnRpbnVlIGV4cGxvcmluZyB0aGUgZGF0YSwgYW5kIHByb3ZpZGUgYSBicmllZiBzdW1tYXJ5IG9mIHdoYXQgeW91IGRpc2NvdmVyLgpUbyBkbwoKOS4gVGhpcyBleGVyY2lzZSBpbnZvbHZlcyB0aGUgQXV0byBkYXRhIHNldCBzdHVkaWVkIGluIHRoZSBsYWIuIE1ha2Ugc3VyZSB0aGF0IHRoZSBtaXNzaW5nIHZhbHVlcyBoYXZlIGJlZW4gcmVtb3ZlZCBmcm9tIHRoZSBkYXRhLgpgYGB7cn0KaGVhZChBdXRvKQpgYGAKKGEpIFdoaWNoIG9mIHRoZSBwcmVkaWN0b3JzIGFyZSBxdWFudGl0YXRpdmUsIGFuZCB3aGljaCBhcmUgcXVhbGktIHRhdGl2ZT8KYGBge3J9CmxhcHBseShBdXRvWy1uY29sKEF1dG8pXSwgc3VtbWFyeSkKIyBtcGcgLSBxdWFudAojIGN5bGluZGVycyAtIHF1YWxpCiMgZGlzcGxhY2VtZW50IC0gcXVhbnRpCiMgaG9yc2Vwb3dlciAtIHF1YW50aQojIHdlaWdodCAtIHF1YW50aQojIGFjY2VsZXJhdGlvbiAtIHF1YW50aQojIHllYXIgLSBxdWFudGkKIyBvcmlnaW4gLSBxdWFsaXQKIyBuYW1lIC0gcXVhbGkgLSBPTUlUVEVEIGJlY2F1c2Ugb2YgbG9uZyBvdXRwdXQKYGBgCgooYikgV2hhdCBpcyB0aGUgcmFuZ2Ugb2YgZWFjaCBxdWFudGl0YXRpdmUgcHJlZGljdG9yPyBZb3UgY2FuIGFuc3dlciB0aGlzIHVzaW5nIHRoZSByYW5nZSgpIGZ1bmN0aW9uLgoKYGBge3J9CmxhcHBseShBdXRvW2MoIm1wZyIsICJkaXNwbGFjZW1lbnQiLCAiaG9yc2Vwb3dlciIsICJ3ZWlnaHQiLCAiYWNjZWxlcmF0aW9uIiwgInllYXIiKV0sIHJhbmdlKQpgYGAKCihjKSBXaGF0IGlzIHRoZSBtZWFuIGFuZCBzdGFuZGFyZCBkZXZpYXRpb24gb2YgZWFjaCBxdWFudGl0YXRpdmUgcHJlZGljdG9yPwpgYGB7cn0KbGFwcGx5KEF1dG9bYygibXBnIiwgImRpc3BsYWNlbWVudCIsICJob3JzZXBvd2VyIiwgIndlaWdodCIsICJhY2NlbGVyYXRpb24iLCAieWVhciIpXSwgbWVhbikKYGBgCihkKSBOb3cgcmVtb3ZlIHRoZSAxMHRoIHRocm91Z2ggODV0aCBvYnNlcnZhdGlvbnMuIFdoYXQgaXMgdGhlIHJhbmdlLCBtZWFuLCBhbmQgc3RhbmRhcmQgZGV2aWF0aW9uIG9mIGVhY2ggcHJlZGljdG9yIGluIHRoZSBzdWJzZXQgb2YgdGhlIGRhdGEgdGhhdCByZW1haW5zPwpgYGB7cn0KYmFzaWMgPC0gZnVuY3Rpb24oeCkgewogIHN1bW1hcnkgPC0gYyhtZWFuID0gbWVhbih4LCBuYS5ybSA9IFQpLCByYW5nZSA9IHJhbmdlKHgsIG5hLnJtID0gVCksIHNkID0gc2QoeCwgbmEucm0gPSBUKSkKICBzdW1tYXJ5Cn0KCmxhcHBseShBdXRvWy0oMTA6ODUpLCAtbmNvbChBdXRvKV0sIGJhc2ljKQpgYGAKCihlKSBVc2luZyB0aGUgZnVsbCBkYXRhIHNldCwgaW52ZXN0aWdhdGUgdGhlIHByZWRpY3RvcnMgZ3JhcGhpY2FsbHksIHVzaW5nIHNjYXR0ZXJwbG90cyBvciBvdGhlciB0b29scyBvZiB5b3VyIGNob2ljZS4gQ3JlYXRlIHNvbWUgcGxvdHMgaGlnaGxpZ2h0aW5nIHRoZSByZWxhdGlvbnNoaXBzIGFtb25nIHRoZSBwcmVkaWN0b3JzLiBDb21tZW50IG9uIHlvdXIgZmluZGluZ3MuCmBgYHtyfQpwbG90KEF1dG9bMTpuY29sKEF1dG8pIC0gMV0pCmBgYApJdCdzIGludGVyZXN0aW5nIHRvIGxvb2sgdGhlIG1wZyBpcyBuZWdhdGl2ZWx5IHJlbGF0ZWQgdG8gZGlzcGxhY2VtZW50LCBob3JzZXBvd2VyIGFuZCB3ZWlnaHQgaW4gYSBzaW1pbGFyIGZhc2hpb24uIEluIGZhY3QsIHRoZSBjb3JyZWxhdGlvbiBhcmU6CmBgYHtyfQpjb3JyZWxhdGlvbnMgPC0gYyhmaXJzdCA9IGNvcihBdXRvJG1wZywgQXV0byRkaXNwbGFjZW1lbnQpLCBzZWNvbmQgPSBjb3IoQXV0byRtcGcsIEF1dG8kaG9yc2Vwb3dlciksIHRoaXJkID0gY29yKEF1dG8kbXBnLCBBdXRvJHdlaWdodCkpCmNvcnJlbGF0aW9ucwpgYGAKQWxsIHdpdGhpbiBhIDUgZmlndXJlIGRpZmZlcmVuY2UuIGFuZCBhYm92ZSAtMC43MC4gSW4gY29udHJhc3QsIHRoZSBjb3JyZWxhdGlvbnMgYmV0d2VlbiBkaXNwbGFjZW1lbnQsIGhvcnNlcG93ZXIgYW5kIHdlaWdodCBhcmUgc3Ryb25nIGFuZCBwb3NpdGl2ZS4KCmBgYHtyfQoKY29ycmVsYXRpb25zMiA8LSBjKGRpc3BsYV9ob3JzZSA9IGNvcihBdXRvJGRpc3BsYWNlbWVudCwgQXV0byRob3JzZXBvd2VyKSwgZGlzcGxhY2Vfd2VpZ2h0ID0gY29yKEF1dG8kZGlzcGxhY2VtZW50LCBBdXRvJHdlaWdodCksIGhvcnNlcF93ZWlnaHQgPSBjb3IoQXV0byRob3JzZXBvd2VyLCBBdXRvJHdlaWdodCkpCgpjb3JyZWxhdGlvbnMyCmBgYAoKYGBge3IgcGhlbm90eXBlLCBmaWcuaGVpZ2h0PTEwLCBmaWcud2lkdGg9MX0KcGxvdChBdXRvJGRpc3BsYWNlbWVudCwgQXV0byRob3JzZXBvd2VyKQpwbG90KEF1dG8kZGlzcGxhY2VtZW50LCBBdXRvJHdlaWdodCkKcGxvdChBdXRvJGhvcnNlcG93ZXIsIEF1dG8kd2VpZ2h0KQpgYGAKCihmKSBTdXBwb3NlIHRoYXQgd2Ugd2lzaCB0byBwcmVkaWN0IGdhcyBtaWxlYWdlIChtcGcpIG9uIHRoZSBiYXNpcyBvZiB0aGUgb3RoZXIgdmFyaWFibGVzLiBEbyB5b3VyIHBsb3RzIHN1Z2dlc3QgdGhhdCBhbnkgb2YgdGhlIG90aGVyIHZhcmlhYmxlcyBtaWdodCBiZSB1c2VmdWwgaW4gcHJlZGljdGluZyBtcGc/IEp1c3RpZnkgeW91ciBhbnN3ZXIuCgpZZWFoLCBqdXN0IGFzIHdlIHNhdyBpbiB0aGUgbWF0cml4IHNjYXR0ZXJwbG90LCBtcGcgaXMgaGlnaGx5IGNvcnJlbGF0ZWQgd2l0aCBzZXZlcmFsIHZhcmlhYmxlcy4gTm90IG9ubHkgdmlzdWFsbHksIGJ1dCB0aGUgY29ycmVsYXRpb24gY29lZmZpY2llbnRzIGFyZSBzdWJzdGFudGlhbC4KCjEwLiAKKGEpIFRvIGJlZ2luLCBsb2FkIGluIHRoZSBCb3N0b24gZGF0YSBzZXQuCmBgYHtyfQpsaWJyYXJ5KE1BU1MpCmhlYWQoQm9zdG9uKQpgYGAKCkhvdyBtYW55IHJvd3MgYXJlIGluIHRoaXMgZGF0YSBzZXQ/IEhvdyBtYW55IGNvbHVtbnM/IFdoYXQgZG8gdGhlIHJvd3MgYW5kIGNvbHVtbnMgcmVwcmVzZW50PwoKYGBge3J9CmRpbShCb3N0b24pCmBgYApUaGUgZGF0YSBoYXMgNTA2IHJvd3MgYW5kIDE0IGNvbHVtbnMuIEVhY2ggcm93IHJlcHJlc2VudHMgaG91c2luZyB2YWx1ZXMgaW4gc3VidXJicyBmcm9tIEJvc3Rvbi4gU2VlIGBoZWxwKEJvc3RvbilgLgoKKGIpIE1ha2Ugc29tZSBwYWlyd2lzZSBzY2F0dGVycGxvdHMgb2YgdGhlIHByZWRpY3RvcnMgKGNvbHVtbnMpIGluIHRoaXMgZGF0YSBzZXQuIERlc2NyaWJlIHlvdXIgZmluZGluZ3MuCmBgYHtyLCBmaWcud2lkdGg9NywgZmlnLmhlaWdodD03fQpwbG90KEJvc3RvbikKYGBgCldlbGwsIGJlc2lkZXMgdGhlIGFycmF5IG9mIGNvcnJlbGF0aW9ucyB0aGF0IHlvdSBjYW4gZmluZCBpbiB0aGUgc2NhdHRlcnBsb3QsIEkgZmluZCBpbnRlcmVzdGluZyB0aGF0IHRoZXJlJ3Mgc29tZSBjbGVhciBub24tbGluZWFyIHBhdHRlcm5zIHN1Y2ggYXMgaW4gYG5veCB+IGRpc2AgYXMgd2VsbCBhcyBgSXN0YXQgfiBtZWR2YCBhbmQgYHJtIH4gSXN0YXRgLgoKKGMpIEFyZSBhbnkgb2YgdGhlIHByZWRpY3RvcnMgYXNzb2NpYXRlZCB3aXRoIHBlciBjYXBpdGEgY3JpbWUgcmF0ZT8gSWYgc28sIGV4cGxhaW4gdGhlIHJlbGF0aW9uc2hpcC4KCmBjcmltYCBpcyBjb3JyZWxhdGVkIHdpdGggYGFnZWAsIGBkaXZgLCBgbHN0YXRgIGFuZCBgbWVkdmAuIFRoZSByZWxhdGlvbnNoaXBzIGFyZSBub3Qgc3RyYWlnaHRmb3J3YXJkIHRob3VnaC4KCmBgYHtyfQpmb3IgKGkgaW4gYygiYWdlIiwgImRpcyIsICJsc3RhdCIsICJtZWR2IikpIHsKcGxvdChCb3N0b25bLCBpXSwgQm9zdG9uWywiY3JpbSJdLCB4bGFiID0gcGFzdGUoaSkpCn0KYGBgCkFzIHRoZSBwcm9wb3J0aW9uIG9mIG93bmVyLW9jY3VwaWVkIHVuaXRzIGJ1aXRsIHByaW9yIHRvIDE5NDAgaW5jcmVhc2VzLCBjcmltZSByYXRlcyBpbmNyZWFzZS4gQnV0IG5vdGUgdGhhdCB0aGVyZSdzIHRocmVzaG9sZCBlZmZlY3RzLiBBdCBhcm91bmQgNDAlIGNyaW1lIHJhdGVzIHN0YXJ0IHRvIGluY3JlYXNlIGFuZCBvbmx5IGFyb3VuZCA4MCUgaXQgYmVjb21lcyBzdWJzdGFudGlhbC4gVGhpcyByZWxhdGlvbnNoaXAgbWlnaHQgbm90IGJlIHRoYXQgc3Ryb25nIGxpbmVhcmx5LCBidXQgbW9yZSBub24tbGluZWFyLgoKV2l0aCBkaXMgKGRpc3RhbmNlIHRvIGZpdmUgQm9zdG9uIGVtcGxveW1lbnQgY2VudHJlcyksIGNyaW1lIHJhdGVzIGFyZSBoaWdoZXIgb25seSB3aGVuIGVtcGxveW1lbnQgY2VudGVycyBhcmUgY2xvc2UsIGJ1dCBhcyBpdCBwYXNzZXMgaW5jcmVhc2VzIG92ZXIgNCwgY3JpbWUgcmF0ZXMgc2V0IGF0IDAuCgpXaXRoIGBsc3RhdGAgaXQncyBzaW1pbGFyIGFzIHdpdGggYGFnZWAsIGNyaW1lIHJhdGVzIGluY3JlYXNlcyBvbmx5IGFmdGVyIHNvbWUgdmFsdWUsIG1vcmUgb3IgbGVzcyBhcm91bmQgMTUuIEl0IHNlZW1zIHRoYXQgY3JpbWUgcmF0ZXMgYXJlIG5vdCBsaW5lYXJseSByZWxhdGVkIHRvIGFsbW9zdCBhbnkgdmFyaWFibGU7IGl0J3MgbW9zdGx5IG5vbi1saW5lYXJseSByZWxhdGVkLiBTYW1lIHBhdHRlcm4gd2l0aCBgbWVkdmAKCihkKSBEbyBhbnkgb2YgdGhlIHN1YnVyYnMgb2YgQm9zdG9uIGFwcGVhciB0byBoYXZlIHBhcnRpY3VsYXJseSBoaWdoIGNyaW1lIHJhdGVzPyBUYXggcmF0ZXM/IFB1cGlsLXRlYWNoZXIgcmF0aW9zPyBDb21tZW50IG9uIHRoZSByYW5nZSBvZiBlYWNoIHByZWRpY3Rvci4KYGBge3J9CmxpYnJhcnkoY2FyKQpCb3hwbG90KEJvc3RvbiRjcmltKQpgYGAKQWJvdmUgdGhlIGdyYXBoIHdlIGNhbiBzZWUgdGhlIG91dGxpZXJzIHdoaWNoIGhhdmUgc2lnbmlmaWNhbnRseSBoaWdoZXIgY3JpbWUgcmF0ZXMgdGhhbiB0aGUgb3ZlcmFsbCBkaXN0cmlidXRpb24uIDEwIHN1YnVyYnMsIHNvIG5vdCBzcGVjaWZpY2FsbHkgYSBzbWFsbCBidW5jaC4KYGBge3J9CkJveHBsb3QoQm9zdG9uJHB0cmF0aW8pCkJveHBsb3QoQm9zdG9uJHRheCkKYGBgCmBwdHJhdGlvYCBkb2VzIGhhdmUgc29tZSBvdXRsaWVycywgYnV0IHRoZXkncmUgbm90IHRoZSBzYW1lIG9uZXMgYXMgd2l0aCBjcmltZSByYXRlcy4gU3VycHJpc2luZ2x5LCBgdGF4YCBkb2VzbmB0IGhhdmUgYW55IG91dGxpZXJzLCBhbmQgdGhlIGRpc3RyaWJ1dGlvbiBpcyBwcmV0dHkgc21vb3RoLgoKYGBge3J9Cgpmb3IgKGkgaW4gYygiY3JpbSIsICJwdHJhdGlvIiwgInRheCIpKSB7CiAgcHJpbnQocmFuZ2UoQm9zdG9uWywgaV0pKQp9CmBgYApUaGUgcmFuZ2Ugb2YgY3JpbWUgcmF0ZXMgY2FuIGJlIGFzIGhpZ2ggYXMgODglIGFuZCBhcyBsb3cgYXMgMCUsIHF1aXRlIHNvbWUgZGl2ZXJzaXR5IGJldHdlZW4gc3VidXJicy4gU3R1ZGVudC10ZWFjaGVyIHJhdGlvIGlzIG11Y2ggc21hbGxlciwgd2l0aCBhIG1heGltdW0gb2YgMjIgc3R1ZGVudHMgYW5kIGEgbWluaW11bSBvZiAxMy4gVGF4IHJhbmdlcyBmcm9tIDE4NyB0byA3MTEuCgooZSkgSG93IG1hbnkgb2YgdGhlIHN1YnVyYnMgaW4gdGhpcyBkYXRhIHNldCBib3VuZCB0aGUgQ2hhcmxlcyByaXZlcj8KCmBgYHtyfQp0YWJsZShCb3N0b24kY2hhcykKYGBgCjM1IHN1YnVycy4KCihmKSBXaGF0IGlzIHRoZSBtZWRpYW4gcHVwaWwtdGVhY2hlciByYXRpbyBhbW9uZyB0aGUgdG93bnMgaW4gdGhpcyBkYXRhIHNldD8KYGBge3J9Cm1lZGlhbihCb3N0b24kcHRyYXRpbykKYGBgCjE5IHB1cGlscyBwZXIgdGVhY2hlci4KCihnKSBXaGljaCBzdWJ1cmIgb2YgQm9zdG9uIGhhcyBsb3dlc3QgbWVkaWFuIHZhbHVlIG9mIG93bmVyLSBvY2N1cGllZCBob21lcz8gV2hhdCBhcmUgdGhlIHZhbHVlcyBvZiB0aGUgb3RoZXIgcHJlZGljdG9ycyBmb3IgdGhhdCBzdWJ1cmIsIGFuZCBob3cgZG8gdGhvc2UgdmFsdWVzIGNvbXBhcmUgdG8gdGhlIG92ZXJhbGwgcmFuZ2VzIGZvciB0aG9zZSBwcmVkaWN0b3JzPyBDb21tZW50IG9uIHlvdXIgZmluZGluZ3MuCgpgYGB7cn0KQm9zdG9uW0Jvc3RvbiRtZWR2ID09IG1pbihCb3N0b24kbWVkdiksIF0KYGBgCkFjdHVhbGx5LCBib3RoIHN1YnVyYiAzOTkgYW5kIDQwNiBoYXZlIHRoZSBzYW1lIGxvd2VzdCBtZWRpYSB2YWx1ZSwgd2hpY2ggaXMgNS4KCkZpcnN0LCBib3RoIHN1YnVycyBoYXZlIHZpcnR1YWxseSB0aGUgc2FtZSB2YWx1ZXMgZm9yIGFsbCBwcmVkaWN0b3JzIGV4Y2VwdCBmb3IgdGhlIGBjcmltYCwgYGxzdGF0YCBhbmQgYGJsYWNrYC4KCgooaCkgSW4gdGhpcyBkYXRhIHNldCwgaG93IG1hbnkgb2YgdGhlIHN1YnVyYnMgYXZlcmFnZSBtb3JlIHRoYW4gc2V2ZW4gcm9vbXMgcGVyIGR3ZWxsaW5nPyBNb3JlIHRoYW4gZWlnaHQgcm9vbXMgcGVyIGR3ZWxsaW5nPyBDb21tZW50IG9uIHRoZSBzdWJ1cmJzIHRoYXQgYXZlcmFnZSBtb3JlIHRoYW4gZWlnaHQgcm9vbXMgcGVyIGR3ZWxsaW5nLgo=